<?php
/**
 * Created by PhpStorm.
 * User: chenyeubin
 * Date: 2020\2\17 0017
 * Time: 16:23
 */

namespace services\patient;

use api\modules\v1\forms\patient\PatientForm;
use common\models\patient\UserAttr;
use common\helpers\CommonHelper;
use common\models\clinic\Clinic;
use common\models\common\Config;
use common\models\marketing\CallbackStatus;
use common\models\marketing\OutpatientType;
use common\models\marketing\SourceChannel;
use common\models\marketing\RiskType;
use common\models\member\Attr;
use common\models\member\Member;
use common\models\patient\BodyParts;
use common\models\patient\OperateLog;
use common\models\patient\Callback;
use common\models\patient\Tags;
use common\models\patient\User;
use common\models\patient\ReportCallback;
use common\models\base\Profession;
use common\models\base\PatientDiseases;
use common\models\rbac\Department;
use common\models\task\Task;
use common\components\Service;
use services\common\CommonService;
use services\log\MemberOperateLogService;
use services\log\PatientOperateLogService;
use services\statistics\ManagementReportService;
use services\task\TaskService;
use Yii;
use yii\db\Expression;
use yii\web\HttpException;

class CallbackService extends Service
{
    /**
     * 根据ID查找信息
     *
     * @param int $id
     * @return Callback|null
     */
    public function findById(int $id = 0): ?Callback
    {
        return Callback::find()->where(['id' => $id])->one();
    }

    /**
     * 查找信息
     *
     * @param array $condition
     * @return Callback|null
     */
    public function findInfo(array $condition = []): ?Callback
    {
        $query = Callback::find();

        // condition
        isset($condition['project_id']) && $query->andWhere(['project_id' => $condition['project_id']]);
        isset($condition['status']) && $query->andWhere(['status' => $condition['status']]);

        // orderBy
        isset($condition['orderBy']) && $query->orderBy($condition['orderBy']);
//        echo $query->createCommand()->getRawSql();exit();
        return $query->one();
    }

    /**
     * 待回访/已回访列表
     *
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @param int $type
     * @return array
     */
    public function getListPage(array $params = [], int $page = 0, int $pageSize = 0, int $type = 0, $unImproved = 0)
    {
        $query = $this->createReFollowQuery($params, $type, $unImproved);
        // 总数
        $total = $query->count();

        // 分页
        if ($page && $pageSize) {
            $query->limit($pageSize)->offset(($page - 1) * $pageSize);
        }

        $list = $query->asArray()->all();

        return [
            'page' => (int)$page,
            'pageSize' => (int)$pageSize,
            'total' => (int)$total,
            'list' => $list,
        ];
    }

    /**
     * 回访列表
     * @param array $params [
     *      'customer' => 1,// 1客服、2医助、3其他（两者都查，待办事项使用）
     * ]
     * @param int $type 【1：已回访，0：待回访，2：待办事项】
     * @return mixed
     */
    public function createReFollowQuery(array $params = [], int $type, $unImproved = 0)
    {
        if ($type == 0 || $type == 2) {
            if ($params['customer'] == 1) {
                $showTimeField = 'a.kf_next_callback_time';
            } else {
                $showTimeField = 'a.yz_next_callback_time';
            }
        } else {
            if ($params['customer'] == 1) {
                $showTimeField = 'a.kf_last_callback_time';
            } else {
                $showTimeField = 'a.yz_last_callback_time';
            }
        }
        $query = User::find()->select([
            'a.id',
            'a.project_id',
            'a.patient_card_id',
            'a.name',
            'a.age',
            'a.gender',
            'a.mobile',
            'a.city_name',
            'a.belong_member_id',
            'a.belong_assistant_id',
            'a.patient_tags_name',
            'a.last_callback_time',
            'a.kf_last_callback_time',
            'a.yz_last_callback_time',
            'a.yz_last_callback_user',
            'a.kf_last_callback_user',
            'a.last_revisiting_time',
            'a.next_callback_time',
            'a.kf_next_callback_time',
            'a.yz_next_callback_time',
            'a.next_revisiting_time',
            'a.callback_count',
            'a.kf_callback_count',
            'a.yz_callback_count',
            'a.missed_days',
            'a.revisiting_count',
            'a.outpatient_type_id',
            'a.source_channel_id',
            'a.remark',
            'b.source_name',
            'c.outpatient_name',
            'd.name AS clinic_name',
            'group_concat(distinct f.body_parts_id) AS body_parts_id',
            'a.city_id',
            'a.patient_diseases_id',
            'a.degree_num',
            'a.effect_type_id',
            'a.risk_type_id',
            'ua.in_hospital_status',
        ])
            ->alias('a')
            ->leftJoin(SourceChannel::tableName() . ' AS b', 'b.id = a.source_channel_id')
            ->leftJoin(OutpatientType::tableName() . ' AS c', 'c.id = a.outpatient_type_id')
            ->leftJoin(Clinic::tableName() . ' AS d', 'd.id = a.clinic_id')
            ->leftJoin(Tags::tableName() . ' AS e', 'e.patient_user_id = a.id')
            ->leftJoin(BodyParts::tableName() . ' AS f', 'f.patient_user_id = a.id AND f.status = ' . BodyParts::STATUS_ENABLE)
            ->leftJoin(UserAttr::tableName() . ' ua', 'a.id = ua.patient_user_id')
            ->where([
                'a.project_id' => $params['project_id'],
                'a.status' => [User::STATUS_INVALID, User::STATUS_ENABLE],
            ]);
        if ($params['customer'] == 1) { // 客服回访
            $query->andWhere(['>', 'a.belong_member_id', 0]);
        } else {
            $query->andWhere(['>', 'a.belong_assistant_id', 0]);
        }

        if ($type == 2) {// 待办事项展示自己
            if ($params['customer'] == 1) {
                $query->andWhere(['a.belong_member_id' => Yii::$app->user->identity->member_id]);
            } elseif ($params['customer'] == 2) {
                $query->andWhere(['a.belong_assistant_id' => Yii::$app->user->identity->member_id]);
            } else {
                $query->andWhere([
                    'or',
                    ['in', 'a.belong_member_id', Yii::$app->user->identity->member_id],
                    ['in', 'a.belong_assistant_id', Yii::$app->user->identity->member_id],
                ]);
            }
        } else {
            if (Yii::$app->user->identity->member->is_super == Member::IS_SUPER_NO) {
                $attr = Yii::$app->services->attr->findInfo([
                    'member_id' => Yii::$app->user->identity->member_id,
                    'project_id' => $params['project_id'],
                ]);
                if ($attr->is_department_leader == Attr::IS_DEPARTMENT_LEADER_NO) {// 普通员工【自己】
                    $memberList = [Yii::$app->user->identity->member_id];
                } elseif ($attr->is_department_leader == Attr::IS_DEPARTMENT_LEADER_YES) {// 部门负责人【部门下所有员工】
                    $attrList = Yii::$app->services->attr->findList([
                        'project_id' => $params['project_id'],
                        'department_id' => $attr->department_id,
                    ]);
                    $memberList = array_column($attrList, 'member_id');
                } else {// 项目负责人【项目下员工】
                    $attrList = Yii::$app->services->attr->findList(['project_id' => $params['project_id']]);
                    $memberList = array_column($attrList, 'member_id');
                }
                if ($params['customer'] == 1) {
                    $query->andWhere(['in', 'a.belong_member_id', $memberList]);
                } else {
                    $query->andWhere(['in', 'a.belong_assistant_id', $memberList]);
                }
            }
        }

        if (isset($params['keywords']) && $params['keywords']) {// 如果有关键词
            // 关键词
            if (isset($params['keywords']) && $params['keywords']) {
                if (preg_match("/([\x81-\xfe][\x40-\xfe])/", $params['keywords'], $match) || preg_match("/(^[A-Za-z]+$)/",$params['keywords'])) {
                    $query->andWhere(['like', 'a.name', "{$params['keywords']}%", false]);
                } else {
                    $query->andWhere([
                        'or',
                        ['a.mobile' => trim($params['keywords'])],
                        ['a.patient_card_id' => trim($params['keywords'])],
                    ]);
                }
            }
        } else {
            // 标签
            if (isset($params['tags_id']) && $params['tags_id']) {
                $query->andWhere(['in', 'e.tags_id', array_filter(explode(',', $params['tags_id']))]);
            }
            // 日期
            if (isset($params['start_time']) && $params['start_time']) {
                $query->andWhere(['>=', $showTimeField, strtotime($params['start_time'])]);
            }
            if (isset($params['end_time']) && $params['end_time']) {
                $query->andWhere(['<=', $showTimeField, strtotime($params['end_time'] . ' 23:59:59')]);
            }
            if ((!isset($params['un_improved']) || !$params['un_improved']) && (!isset($params['start_time']) || !$params['start_time']) && (!isset($params['end_time']) || !$params['end_time'])) {
                if (isset($params['re_follow']) && $params['re_follow'] == 1) {
                    $query->andWhere(['>=', $showTimeField, strtotime(date("Y-m-d 00:00:00"))]);
                } elseif (isset($params['re_todo']) && $params['re_todo'] == 1) {
                    $query->andWhere(['>=', $showTimeField, strtotime(date("Y-m-d 00:00:00"))]);
                    $query->andWhere(['<=', $showTimeField, strtotime(date("Y-m-d 23:59:59"))]);
                } else {
                    //$query->andWhere(['>=', $showTimeField, strtotime(date("Y-m-d 00:00:00"))]);
                    $query->andWhere(['<=', $showTimeField, strtotime(date("Y-m-d 23:59:59"))]);
                }
            }

            // 未完善列表
            if (isset($params['un_improved']) && $params['un_improved']) {
                $query->andWhere([
                    'or',
                    ['a.name' => ''],
                    ['a.mobile' => ''],
                    ['a.city_id' => 0],
                    ['a.patient_diseases_id' => 0],
                    ['a.gender' => 0],
                    ['a.patient_body_parts_name' => ''],
                    ['a.patient_tags_name' => ''],
                    ['a.risk_type_id' => 0],
                    ['a.effect_type_id' => 0],
                ]);
            }
            // 归属人
            if (isset($params['belong_member_id']) && $params['belong_member_id']) {
                if ($params['customer'] == 1) {
                    $query->andWhere(['a.belong_member_id' => $params['belong_member_id']]);
                } else {
                    $query->andWhere(['a.belong_assistant_id' => $params['belong_member_id']]);
                }
            }
            // 就诊类型
            if (isset($params['outpatient_type_id']) && $params['outpatient_type_id']) {
                $query->andWhere(['a.outpatient_type_id' => $params['outpatient_type_id']]);
            }

            // 上次回访人
            if (isset($params['last_callback_user_id']) && $params['last_callback_user_id']) {
                if ($params['customer'] == 1) {
                    $query->andWhere(['a.kf_last_callback_id' => $params['last_callback_user_id']]);
                    $query->andWhere('`kf_last_callback_time` > `yz_last_callback_time`');
                } else if ($params['customer'] == 2) {
                    $query->andWhere(['a.yz_last_callback_id' => $params['last_callback_user_id']]);
                    $query->andWhere('`yz_last_callback_time` > `kf_last_callback_time`');
                }
            }

            // 是否住院
            if (isset($params['in_hospital']) && $params['in_hospital'] ) {
                if ($params['in_hospital'] == UserAttr::IS_HOSPITAL_YES) {
                    $query->andWhere(['ua.in_hospital_status' => UserAttr::STATUS_IN_HOSPITAL]);
                } else {
                    $query->andWhere(['ua.in_hospital_status' => [UserAttr::STATUS_NO_HOSPITAL, UserAttr::STATUS_OUT_HOSPITAL]]);
                }
            }
        }

        // 待完善列表中默认查询全局配置里面的就诊类型数据
        if ($unImproved == 1) {
            if ($params['customer'] == 1) {// 客服就诊类型
                $config = Yii::$app->services->config->findInfo([
                    'config_name' => Config::CONFIG_NAME_CUSTOMER_OUTPATIENT,
                    'project_id' => $params['project_id']
                ]);
                $ids = [];
                if ($config && $config->config_value) {
                    $ids = explode(',', $config->config_value);
                }
                $query->andWhere(['a.outpatient_type_id' => $ids]);
            }
        }
        // 排序
        $orderBy = [];
        if (isset($params['last_revisiting_time_type']) && $params['last_revisiting_time_type']) {// 上次到诊时间
            if ($params['last_revisiting_time_type'] == 1) {
                $orderBy = ['a.last_revisiting_time' => SORT_ASC];
            } elseif ($params['last_revisiting_time_type'] == 2) {
                $orderBy = ['a.last_revisiting_time' => SORT_DESC];
            }
        } elseif (isset($params['next_revisiting_time_type']) && $params['next_revisiting_time_type']) {// 下次复诊次数
            if ($params['next_revisiting_time_type'] == 1) {
                $orderBy = ['a.next_revisiting_time' => SORT_ASC];
            } elseif ($params['next_revisiting_time_type'] == 2) {
                $orderBy = ['a.next_revisiting_time' => SORT_DESC];
            }
        } elseif (isset($params['last_callback_time_type']) && $params['last_callback_time_type']) {// 上次回访时间
            if ($params['customer'] == 1) {
                if ($params['last_callback_time_type'] == 1) {
                    $orderBy = ['a.kf_last_callback_time' => SORT_ASC];
                } elseif ($params['last_callback_time_type'] == 2) {
                    $orderBy = ['a.kf_last_callback_time' => SORT_DESC];
                }
            } else {
                if ($params['last_callback_time_type'] == 1) {
                    $orderBy = ['a.yz_last_callback_time' => SORT_ASC];
                } elseif ($params['last_callback_time_type'] == 2) {
                    $orderBy = ['a.yz_last_callback_time' => SORT_DESC];
                }
            }
        } elseif (isset($params['next_callback_time_type']) && $params['next_callback_time_type']) {// 下次回访时间
            if ($params['customer'] == 1) {
                if ($params['next_callback_time_type'] == 1) {
                    $orderBy = ['a.kf_next_callback_time' => SORT_ASC];
                } elseif ($params['next_callback_time_type'] == 2) {
                    $orderBy = ['a.kf_next_callback_time' => SORT_DESC];
                }
            } else {
                if ($params['next_callback_time_type'] == 1) {
                    $orderBy = ['a.yz_next_callback_time' => SORT_ASC];
                } elseif ($params['next_callback_time_type'] == 2) {
                    $orderBy = ['a.yz_next_callback_time' => SORT_DESC];
                }
            }
        } elseif (isset($params['sort_revisiting_type']) && $params['sort_revisiting_type']) {// 复诊次数
            if ($params['sort_revisiting_type'] == 1) {
                $orderBy = ['a.revisiting_count' => SORT_ASC];
            } elseif ($params['sort_revisiting_type'] == 2) {
                $orderBy = ['a.revisiting_count' => SORT_DESC];
            }
        } elseif (isset($params['sort_missed_type']) && $params['sort_missed_type']) {// 未到诊天数
            if ($params['sort_missed_type'] == 1) {
                $orderBy = ['a.missed_days' => SORT_ASC];
            } elseif ($params['sort_missed_type'] == 2) {
                $orderBy = ['a.missed_days' => SORT_DESC];
            }
        } elseif (isset($params['sort_callback_count_type']) && $params['sort_callback_count_type']) {// 回访次数
            if ($params['sort_callback_count_type'] == 1) {
                $orderBy = ['a.callback_count' => SORT_ASC];
            } elseif ($params['sort_callback_count_type'] == 2) {
                $orderBy = ['a.callback_count' => SORT_DESC];
            }
        } elseif (isset($params['sort_degree_type']) && $params['sort_degree_type']) {// 完善度
            if ($params['sort_degree_type'] == 1) {
                $orderBy = ['a.degree_num' => SORT_ASC];
            } elseif ($params['sort_degree_type'] == 2) {
                $orderBy = ['a.degree_num' => SORT_DESC];
            }
        } elseif (isset($params['sort_patient_card_id']) && $params['sort_patient_card_id']) {// 诊疗号
            if ($params['sort_patient_card_id'] == 1) {
                $orderBy = ['a.patient_card_id' => SORT_ASC];
            } elseif ($params['sort_patient_card_id'] == 2) {
                $orderBy = ['a.patient_card_id' => SORT_DESC];
            }
        } else {
            if ($unImproved == 1) {
                $orderBy = [
                    'a.last_revisiting_time' => SORT_DESC,
                    'a.updated_at' => SORT_DESC,
                ];
            } else {
                $orderBy = ['a.updated_at' => SORT_DESC];
            }
        }
        $query->orderBy($orderBy);
        $orderBy['a.id'] = SORT_DESC;
        $query->groupBy('a.id');
        return $query;
    }

    /**
     * 数据格式化
     * @param array $data
     * @param int $type
     * @return array
     */
    /**
     * @param array $data
     * @param int $type
     * @param int $customer
     * @return array
     * @author chenyuebin
     */
    public function getListPageFormat(array $data, int $type = 0, int $customer = 0)
    {
        $list = [];
        $memberList = Yii::$app->services->member->findList();
        $memberArr = [];
        foreach ($memberList as $value) {
            $memberArr[$value['id']] = $value['realname'];
        }
        foreach ($data as $row) {
            $item = [
                'id' => $row['id'],
                'project_id' => $row['project_id'],
                'name' => $row['name'],
                'age' => $row['age'],
                'gender' => $row['gender'],
                'gender_str' => User::$genders[$row['gender']],
                'patient_card_id' => $row['patient_card_id'],// 诊疗号
                'clinic_name' => $row['clinic_name'] ? $row['clinic_name'] : '',// 诊室
                'risk_type_id' => isset($row['risk_type_id']) ? $row['risk_type_id'] : '',// 风控类型ID
                'effect_type_id' => isset($row['effect_type_id']) ? $row['effect_type_id'] : '',// 效果类型
                'mobile' => $row['mobile'],
                'outpatient_type_id' => $row['outpatient_type_id'],// 就诊类型ID
                'is_first_initially' => $row['outpatient_type_id'] == ManagementReportService::OUTPATIENT_TYPE['initially'] ? true : false,
                'outpatient_name' => $row['outpatient_name'] ? $row['outpatient_name'] : '',// 就诊类型
                'revisiting_count' => $row['revisiting_count'],// 复诊次数
                'callback_count' => $row['callback_count'],// 回访次数
                'missed_days' => $row['missed_days'],// 未到诊天数
                'city_name' => $row['city_name'],// 地区【城市名】
                'source_channel_id' => $row['source_channel_id'],// 来源渠道ID
                'source_name' => $row['source_name'] ? $row['source_name'] : '',// 来源渠道
                'last_revisiting_time_str' => $row['last_revisiting_time'] ? date('Y-m-d', $row['last_revisiting_time']) : '',// 上次复诊时间
                'next_revisiting_time_str' => $row['next_revisiting_time'] ? date('Y-m-d', $row['next_revisiting_time']) : '',// 下次复诊时间
                'last_callback_time_str' => $row['last_callback_time'] ? date('Y-m-d H:i', $row['last_callback_time']) : '',// 上次回访时间
                'next_callback_time_str' => $row['next_callback_time'] ? date('Y-m-d', $row['next_callback_time']) : '',// 下次回访时间
                'patient_tags_name_arr' => $row['patient_tags_name'] ? explode(',', $row['patient_tags_name']) : [],// 患者标签数组
                'remark' => $row['remark'],// 备注
                'body_parts_id' => isset($row['body_parts_id']) ? explode(',', $row['body_parts_id']) : [],// 患病部位
                'patient_diseases_id' => $row['patient_diseases_id'],// 病种
                'city_id' => $row['city_id'],// 病种
                'improved' => $row['degree_num'] * 100 . '%',// 完成度
                'last_callback' => $this->lastCallbak($row['id']) ? $this->lastCallbak($row['id']) : '',// 上一次回访内容
                'last_callback_user' => $row['yz_last_callback_time'] >= $row['kf_last_callback_time'] ? $row['yz_last_callback_user'] : $row['kf_last_callback_user'],// 上次回访人
                'in_hospital_status' => $row['in_hospital_status'] ?? '',
            ];
            if ($customer == 1) {
                $item['last_callback_time_str'] = $row['kf_last_callback_time'] ? date('Y-m-d H:i', $row['kf_last_callback_time']) : '';// 上次回访时间
                $item['next_callback_time_str'] = $row['kf_next_callback_time'] ? date('Y-m-d', $row['kf_next_callback_time']) : '';// 下次回访时间
                /*$item['callback_count'] = $row['kf_callback_count'] ? $row['kf_callback_count'] : 0;// 回访次数(客服)
                $yz_callback_count = $row['yz_callback_count'] ? $row['yz_callback_count'] : 0;// 回访次数（医助）
                $item['callback_count'] += $yz_callback_count;// 回访次数*/
                // $item['last_callback_user'] = $row['kf_last_callback_user'];// 上次回访人
                $item['belong_member_id'] = $row['belong_member_id'];// 归属人
                $item['belong_member_name'] = isset($memberArr[$row['belong_member_id']]) ? $memberArr[$row['belong_member_id']] : '';// 归属人
            } else {
                $item['last_callback_time_str'] = $row['yz_last_callback_time'] ? date('Y-m-d H:i', $row['yz_last_callback_time']) : '';// 上次回访时间
                $item['next_callback_time_str'] = $row['yz_next_callback_time'] ? date('Y-m-d', $row['yz_next_callback_time']) : '';// 下次回访时间
                /*$item['callback_count'] = $row['yz_callback_count'] ? $row['yz_callback_count'] : 0;// 回访次数(医助)
                $kf_callback_count = $row['kf_callback_count'] ? $row['kf_callback_count'] : 0;// 回访次数（客服）
                $item['callback_count'] += $kf_callback_count;// 回访次数*/
                // $item['last_callback_user'] = $row['yz_last_callback_user'] ? $row['yz_last_callback_user'] : '';// 上次回访人
                $item['belong_member_id'] = $row['belong_assistant_id'];// 归属人
                $item['belong_member_name'] = isset($memberArr[$row['belong_assistant_id']]) ? $memberArr[$row['belong_assistant_id']] : '';// 归属人
            }
            if ($type == 1) {
                if ($customer == 1) {
                    $item['diff_day'] = round((time() - $row['kf_next_callback_time']) / 3600 / 24);
                } else {
                    $item['diff_day'] = round((time() - $row['yz_next_callback_time']) / 3600 / 24);
                }
            }

            $list[] = $item;
        }

        return $list;
    }

    /**
     * 患者回访记录
     *
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getPatientListPage(array $params = [], int $page = 0, int $pageSize = 0)
    {
        $query = Callback::find()->select(['a.*', 'b.profession_name'])->alias('a')
            ->leftJoin(Attr::tableName() . ' AS b', 'b.member_id = a.member_id AND b.project_id = a.project_id')
            ->where([
                'a.project_id' => $params['project_id'],
                'a.patient_user_id' => $params['patient_user_id'],
            ])
            ->orderBy(['a.current_callback_time' => SORT_DESC]);

        // 回访时间
        if (isset($params['start_time']) && $params['start_time']) {
            $query->andWhere(['>=', 'a.current_callback_time', strtotime($params['start_time'])]);
        }
        if (isset($params['end_time']) && $params['end_time']) {
            $query->andWhere(['<=', 'a.current_callback_time', strtotime($params['end_time'] . ' 23:59:59')]);
        }

        // 岗位
        if (isset($params['profession_id']) && $params['profession_id']) {
            $query->andWhere(['b.profession_id' => $params['profession_id']]);
        }

        // 总数
        $total = $query->count();

        // 分页
        if ($page && $pageSize) {
            $query->limit($pageSize)->offset(($page - 1) * $pageSize);
        }

        $list = $query->asArray()->all();

        return [
            'page' => (int)$page,
            'pageSize' => (int)$pageSize,
            'total' => (int)$total,
            'list' => $list,
        ];
    }

    /**
     * 患者回访记录 + 添加通话记录
     *
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getPatientListPage2(array $params = [], int $page = 0, int $pageSize = 0)
    {
        // 患者基本信息
        $patientUser = User::find()
            ->select(['name', 'age', 'gender', 'mobile'])
            ->where(['id' => $params['patient_user_id']])
            ->asArray()
            ->one();

        $query1 = Callback::find()->select([
            'a.*', 'b.profession_name', 'a.current_callback_time as created_at',
            new Expression('1 data_type'),
            ])->alias('a')
            ->leftJoin(Attr::tableName() . ' AS b', 'b.member_id = a.member_id AND b.project_id = a.project_id')
            ->where([
                'a.project_id' => $params['project_id'],
                'a.patient_user_id' => $params['patient_user_id'],
            ])
            ->orderBy(['a.current_callback_time' => SORT_DESC]);

        // 回访时间
        if (isset($params['start_time']) && $params['start_time']) {
            $query1->andWhere(['>=', 'a.current_callback_time', strtotime($params['start_time'])]);
        }
        if (isset($params['end_time']) && $params['end_time']) {
            $query1->andWhere(['<=', 'a.current_callback_time', strtotime($params['end_time'] . ' 23:59:59')]);
        }

        // 岗位
        if (isset($params['profession_id']) && $params['profession_id']) {
            $query1->andWhere(['b.profession_id' => $params['profession_id']]);
        }

        $data1 = $query1->orderBy(['a.current_callback_time' => SORT_DESC, 'a.id' => SORT_DESC])->asArray()->all();
        $data2 = CommonHelper::dengta_request('/v1/baiyou/callback-voice-list', [], [
            'mobile' => $patientUser['mobile'],
            'callback_way_id' => Callback::CALLBACK_WAY_ID_TEL,
            'start_time' => $params['start_time'] ?? '',
            'end_time' => $params['end_time'] ?? '',
        ]);

        $data = array_merge($data1, $data2);

        if ($data) {
            foreach ($data as $key => $row) {
                $createdOrder[$key] = $row['created_at'];
                $idOrder[$key] = $row['id'];
            }
            array_multisort(
                $createdOrder, SORT_DESC,
                $idOrder, SORT_DESC,
                $data
            );
        }

        $list = [
            'page' => 0,
            'pageSize' => 0,
            'total' => count($data1) + count($data2),
            'list' => $data,
        ];

        return $list;
    }

    /**
     * 创建通话回访query
     *
     * @param $mobile
     * @return \yii\db\ActiveQuery
     */
//    public function createVocieCallbackQuery($mobile)
//    {
//        $query = Voice::find()->alias('a')
//            ->innerJoin(WechatAccountinfo::tableName() . ' b', 'b.wechatid = a.wechatid AND b.cid=a.cid')
//            ->innerJoin(Phoneinfo::tableName() . ' c','c.deviceid = b.deviceid')
//            ->where([
//                'a.cid' => Yii::$app->params['project_id'],
//                'c.sys_id' => Phoneinfo::SYS_BY,
//                'a.mobile' => $mobile,
//            ])
//            ->andWhere(['!=', 'a.mobile', '']);
//
//        return $query;
//    }

    /**
     * 格式化患者回访列表数据
     *
     * @param array $data
     * @param int $type
     * @return array
     */
    public function getPatientListPageFormat(array $data)
    {
        $list = [];
        foreach ($data as $row) {
            $item = [
                'id' => $row['id'],
                'type' => $row['type'] ?? "",
                'data_type' => $row['data_type'] ?? "",
                'wechatid' => $row['wechatid'] ?? "",
                'deviceid' => $row['deviceid'] ?? "",
                'file_url' => !empty($row['file_url']) ? CommonHelper::parseMessageContent($row['file_url']) : "",
                'duration' => $row['duration'] ?? "",
                'project_id' => $row['project_id'],
                'patient_user_id' => $row['patient_user_id'] ?? "",
                'callback_state_id' => $row['callback_state_id'] ?? "",
                'callback_state' => $row['callback_state'] ?? "",
                'callback_way_id' => $row['callback_way_id'] ?? "",
                'callback_way' =>  !empty($row['callback_way_id']) ? (Callback::$callbackWayIds[$row['callback_way_id']] ?? '其他') : "其他",
                'content' => $row['content'] ?? "",
                'member_id' => $row['member_id'] ?? "",
                'member_name' => $row['member_name'] ?? "",
                'profession_name' =>  !empty($row['profession_name']) ? $row['profession_name'] : '',
                'current_callback_time_str' => !empty($row['current_callback_time']) ? CommonService::timeChangeWeek($row['current_callback_time']) : '',// 本次回访时间
            ];

            $list[] = $item;
        }

        return $list;
    }

    /**
     * 统计患者回访分类总数
     *
     * @param array $params
     * @return array|\yii\db\ActiveRecord[]
     */
    public function getPatientStatusList(array $params = [])
    {
        $query = Callback::find()->select(['a.callback_state_id', 'a.callback_state', 'COUNT(a.id) AS total'])->alias('a')
            ->innerJoin(Attr::tableName() . ' AS b', 'b.member_id = a.member_id AND b.project_id = a.project_id')
            ->where([
                'a.project_id' => $params['project_id'],
                'a.patient_user_id' => $params['patient_user_id'],
            ])
            ->orderBy(['a.callback_state_id' => SORT_ASC])
            ->groupBy('a.callback_state_id');

        // 回访时间
        if (isset($params['start_time']) && $params['start_time']) {
            $query->andWhere(['>=', 'a.current_callback_time', strtotime($params['start_time'])]);
        }
        if (isset($params['end_time']) && $params['end_time']) {
            $query->andWhere(['<=', 'a.current_callback_time', strtotime($params['end_time'] . ' 23:59:59')]);
        }

        // 岗位
        if (isset($params['profession_id']) && $params['profession_id']) {
            $query->andWhere(['b.profession_id' => $params['profession_id']]);
        }

        return $query->asArray()->all();
    }

    /**
     * 同步回访时间数据
     */
    public function synPatientUserCallbackTime()
    {
        set_time_limit(0);
        ini_set('memory_limit', '8G');

        // 患者回访时间
        $query = Callback::find()->alias('a')
            ->select([
                'a.patient_user_id', 'MAX(a.current_callback_time) AS current_callback_time',
                'b.profession_id',
            ])
            ->innerJoin(Attr::tableName() . ' AS b', 'b.member_id = a.member_id AND b.project_id = a.project_id')
            ->groupBy('a.patient_user_id, b.profession_id');

        $query->andWhere([
            'b.profession_id' => [Profession::ID_MEDICAL, Profession::ID_CUSTOMER]
        ]);

        $res = $query->asArray()->all();

        // 患者列表
        $patientUserList = Yii::$app->services->patientUser->findList([
            'select' => ['id', 'kf_last_callback_time', 'yz_last_callback_time'],
            'indexBy' => 'id',
        ]);

        $updateList = [];
        foreach ($res as $row) {
            if ($row['profession_id'] == Profession::ID_CUSTOMER) {// 客服
                if ($patientUserList[$row['patient_user_id']]['kf_last_callback_time'] >= $row['current_callback_time']) {
                    continue;
                }

                $updateList[$row['patient_user_id']]['kf_last_callback_time'] = $row['current_callback_time'];
            } else {// 医助
                if ($patientUserList[$row['patient_user_id']]['yz_last_callback_time'] >= $row['current_callback_time']) {
                    continue;
                }
                $updateList[$row['patient_user_id']]['yz_last_callback_time'] = $row['current_callback_time'];
            }
        }

//        echo count($res).PHP_EOL;
//        echo count($updateList).PHP_EOL;
//        print_r($updateList);
        foreach ($updateList as $key => $row) {
            User::updateAll($row, ['id' => $key]);
            echo $key . PHP_EOL;
        }
    }

    /**
     * 添加回访
     *
     * @param array $params
     * @return array
     */
    public function createFollow(array $params = [])
    {
        $member_id = Yii::$app->user->identity->member_id;
//        $depatment = Attr::find()->alias('a')
//            ->select('b.name')
//            ->leftJoin(Department::tableName() . ' AS b', 'a.department_id = b.id')
//            ->where(['member_id' => $member_id])->asArray()->one();// 获取顾问部门
        $depatment = Department::findOne(Yii::$app->params['department_id']);
        // 获取回访状态名称
        $callbackState = CallbackStatus::findOne($params['callback_state_id']);

        $transaction = Yii::$app->db->beginTransaction();
        try {
            // 1.新增回访
            $callback = new Callback();
            $callback->project_id = $params['project_id'];
            $callback->callback_state_id = $params['callback_state_id'];
            $callback->callback_state = $callbackState->callback_name ?? '';
            $callback->content = $params['content'];
            $callback->callback_way_id = $params['callback_way_id'];
            $callback->next_callback_time = $params['risk_type'] && $params['risk_type'] != RiskType::BLACK_LIST ? strtotime($params['next_callback_time']) : 0;
            $callback->next_fuzhen_time = $params['next_fuzhen_time'] ? strtotime($params['next_fuzhen_time']) : 0;
            $callback->member_id = $member_id;
            $callback->member_name = Yii::$app->user->identity->member->realname;
            $callback->current_callback_time = time();
//            $callback->member_departmement = $depatment ? $depatment['name'] : '';
            $callback->member_departmement = $depatment->name ?? '';
            $callback->patient_user_id = $params['patient_id'];
            $callback->outpatient_type_id = $params['outpatient_type_id'] ?: 0;
            $callback->saveAndCheckResult();

            // 2.更新用户标签
            $model = new PatientForm();
            $model->setScenario('patient_tags');
            $model->attributes = [
                'project_id' => $params['project_id'],
                'id' => $params['patient_id'],
                'tags_ids' => $params['tags_ids'],
            ];
            if (!$model->validate()) {
                throw new \Exception($this->getError($model), 422);
            }
            // 2-1.新增标签
            foreach ($model->getAddTagsIds() as $row) {
                $patientTags = Yii::$app->services->patientTags->findInfo([
                    'patient_user_id' => $model->id,
                    'tags_id' => $row,
                ]);
                if (!$patientTags) {
                    $patientTags = new Tags();
                }
                $patientTags->patient_user_id = $model->id;
                $patientTags->tags_id = $row;
                $patientTags->status = Tags::STATUS_ENABLE;
                $patientTags->saveAndCheckResult();
            }
            // 2-2.删除标签
            Tags::updateAll(['status' => Tags::STATUS_DELETE], ['patient_user_id' => $model->id, 'tags_id' => $model->getDeleteTagsIds()]);

            // 2-1.更新患者
            $patient = $model->getPatient();
            // 患者原信息
            $oldPatient = new User();
            $oldPatient->setAttributes($patient->getAttributes());
            if ($params['isCustomer'] == 1) {
                $patient->kf_last_callback_time = time();
                if ($params['risk_type'] != RiskType::BLACK_LIST) {
                    $patient->kf_next_callback_time = strtotime($params['next_callback_time']);
                }
                $patient->kf_callback_count = $patient->kf_callback_count + 1;
                $patient->kf_last_callback_user = Yii::$app->user->identity->member->realname;
                $patient->kf_last_callback_id = $member_id;
            } else {
                $patient->yz_last_callback_time = time();
                if ($params['risk_type'] != RiskType::BLACK_LIST) {
                    $patient->yz_next_callback_time = strtotime($params['next_callback_time']);
                }
                $patient->yz_callback_count = $patient->yz_callback_count + 1;
                $patient->yz_last_callback_user = Yii::$app->user->identity->member->realname;
                $patient->yz_last_callback_id = $member_id;
            }
            $patient->last_callback_time = time();
            if ($params['risk_type'] != RiskType::BLACK_LIST) {
                $patient->next_callback_time = strtotime($params['next_callback_time']);
            }
            // 更新完善度
            $patient->degree_num = Yii::$app->services->patientUser->computeDegreeNum([
                'name' => $patient->name,
                'mobile' => $patient->mobile,
                'gender' => $patient->gender,
                'city_id' => $patient->city_id,
                'patient_diseases_id' => $patient->patient_diseases_id,
                'body_parts_ids' => $patient->patient_body_parts_name,
                'patient_tags_name' => $params['tags_ids'],
                'outpatient_type_id' => $params['outpatient_type_id'],
                'effect_type_id' => isset($params['effect_type']) ? $params['effect_type'] : '',
                'risk_type_id' => $params['risk_type'],
            ]);
            $patient->risk_type_id = $params['risk_type'];
            $patient->effect_type_id = $params['effect_type'] ?? 0;
            $patient->callback_count = $patient->callback_count + 1;
            $patient->next_revisiting_time = $params['next_fuzhen_time'] ? strtotime($params['next_fuzhen_time']) : 0;
            $patient->patient_tags_name = $model->getPatientTagsName();
            $patient->saveAndCheckResult();

            // 3-1.新增患者操作日志
            PatientOperateLogService::create($params['project_id'], $params['patient_id'], OperateLog::ACTION_TYPE_PATIENT_FOLLOW, '新增患者回访|' . Callback::$callbackWayIds[$params['callback_way_id']]);
            // 3-2.新增用户操作日志
            MemberOperateLogService::createCallbackLog('create', $callback, $model, $patient, $oldPatient);

            // 4.任务更新
            $taskService = new TaskService();
            $taskIds = $taskService->updateCallbackTask((int)$params['patient_id'], $callback->id);

            $transaction->commit();

            // 发送通知
            if ($taskIds) {
                foreach ($taskIds as $row) {
                    $taskService->taskRemind((int)$row, Task::STATUS_SUCCESS);
                }
            }
            return ['id' => $params['patient_id']];
        } catch (\Exception $e) {
            $transaction->rollBack();
            return CommonHelper::api(422, $e->getMessage());
        }
    }

    /**
     * 用户当天的标签列表
     */
    public function callbackTags($patient_user_ids)
    {
        $data = Tags::find()
            ->alias('pt')
            ->select('t.tags_name as title, t.id as value')
            ->leftJoin(\common\models\marketing\Tags::tableName() . ' t', 't.id = pt.tags_id')
            ->groupBy('pt.tags_id')
            ->where(['pt.patient_user_id' => $patient_user_ids])
            ->asArray()
            ->all();

        return $data;
    }

    /**
     * 统计待回访等数据信息
     * @param $member_id 归属人id
     * @param $isCustomer 是否是客服 1 = 客服
     * @return array
     */
    public function callbackData($projectId, $member_id, $isCustomer = 0)
    {
        $ids = [];
        if ($isCustomer == 1) {// 客服就诊类型
            $config = Yii::$app->services->config->findInfo([
                'config_name' => Config::CONFIG_NAME_CUSTOMER_OUTPATIENT,
                'project_id' => $projectId
            ]);

            if ($config && $config->config_value) {
                $ids = explode(',', $config->config_value);
            }
        }

        if ($isCustomer == 1) {
            $lastCallbackTime = 'kf_last_callback_time';
            $nextCallbackTime = 'kf_next_callback_time';
        } else {
            $lastCallbackTime = 'yz_last_callback_time';
            $nextCallbackTime = 'yz_next_callback_time';
        }
        //患者数
        $patientCountQuery = User::find()
            ->where(['project_id' => $projectId, 'status' => User::STATUS_ENABLE]);
        $isCustomer ? $patientCountQuery->andWhere(['belong_member_id' => $member_id]) : $patientCountQuery->andWhere(['belong_assistant_id' => $member_id]);
        $isCustomer ? $patientCountQuery->andWhere(['outpatient_type_id' => $ids]) : '';
        $patientCount = $patientCountQuery->count();

        //今日回访
        $startTime = strtotime(date('Y-m-d') . ' 00:00:00');
        $endTime = strtotime(date('Y-m-d') . ' 23:59:59');
        $completeCount = Callback::find()
            ->where(['between', 'created_at', $startTime, $endTime])
            ->andWhere(['project_id' => $projectId, 'status' => User::STATUS_ENABLE])
            ->andWhere(['member_id' => $member_id])
            ->count();
        // 原版
        /*$completeCountQuery = User::find()
            ->where(['between', $lastCallbackTime, $startTime, $endTime])
            ->andWhere(['project_id' => $projectId, 'status' => User::STATUS_ENABLE]);
        $isCustomer ? $completeCountQuery->andWhere(['belong_member_id' => $member_id]) : $completeCountQuery->andWhere(['belong_assistant_id' => $member_id]);
        $isCustomer ? $completeCountQuery->andWhere(['outpatient_type_id' => $ids]) : '';
        $completeCount = $completeCountQuery->count();*/
        $unfinishedQuery = User::find()
            ->where(['between', $nextCallbackTime, $startTime, $endTime])
            ->andWhere(['project_id' => $projectId, 'status' => User::STATUS_ENABLE]);
        $isCustomer ? $unfinishedQuery->andWhere(['belong_member_id' => $member_id]) : $unfinishedQuery->andWhere(['belong_assistant_id' => $member_id]);
        $isCustomer ? $unfinishedQuery->andWhere(['outpatient_type_id' => $ids]) : '';
        $unfinished = $unfinishedQuery->count();

        //过期未回访
        $stime = mktime(0, 0, 0, date('m'), date('d') - 1, date('Y')) - 1;
        $overdueQuery = User::find()
            ->where(['<', $nextCallbackTime, $startTime])
            ->andWhere(['project_id' => $projectId, 'status' => User::STATUS_ENABLE]);

        $overdueQuery->andWhere([
            'and',
            ['>=', $nextCallbackTime, strtotime(date("Y-m-d 00:00:00", strtotime('-1 day')))],
            ['<=', $nextCallbackTime, strtotime(date("Y-m-d", strtotime('-1 day')) . ' 23:59:59')]
        ]);
        $isCustomer ? $overdueQuery->andWhere(['belong_member_id' => $member_id]) : $overdueQuery->andWhere(['belong_assistant_id' => $member_id]);
        $isCustomer ? $overdueQuery->andWhere(['outpatient_type_id' => $ids]) : '';
        $overdue = $overdueQuery->count();


        return [
            'patientCount' => $patientCount,
            'completeCount' => $completeCount ?? '0',
            'unfinished' => $unfinished ?? '0',
            'overdue' => $overdue ?? '0',
        ];
    }

    /**
     * 定时统计已回访、未回访数据
     * @return int
     * @throws \yii\db\Exception
     * @author chenyuebin
     */
    public function reportCallback()
    {
        $start_time = strtotime(date('Y-m-d 00:00:00', strtotime('-1 day')));
        $end_time = strtotime(date('Y-m-d 23:59:59', strtotime('-1 day')));

        $memberInfo = Attr::find()
            ->select([
                'member_id',
                'profession_id'
            ])
            ->where([
                'and',
                ['profession_id' => 301],
                ['profession_id' => 302]
            ])
            ->groupBy('member_id')
            ->asArray()
            ->all();
        $memberList = [];
        foreach ($memberInfo as $value) {
            $memberList[$value['member_id']] = $value['profession_id'];
        }

        $kfFollowData = User::find()
            ->select([
                'kf_last_callback_time',
                'kf_next_callback_time',
                'project_id',
                'id',
                'belong_member_id'
            ])
            ->where([
                'and',
                ['>=', 'kf_last_callback_time', $start_time],
                ['<=', 'kf_last_callback_time', $end_time]
            ])
            ->orWhere([
                'and',
                ['>=', 'kf_next_callback_time', $start_time],
                ['<=', 'kf_next_callback_time', $end_time],
                ['<', 'kf_last_callback_time', $start_time]
            ])
            ->asArray()
            ->all();

        $yzFollowData = User::find()
            ->select([
                'yz_last_callback_time',
                'yz_next_callback_time',
                'project_id',
                'id',
                'belong_assistant_id'
            ])
            ->where([
                'and',
                ['>=', 'yz_last_callback_time', $start_time],
                ['<=', 'yz_last_callback_time', $end_time]
            ])
            ->orWhere([
                'and',
                ['>=', 'yz_next_callback_time', $start_time],
                ['<=', 'yz_next_callback_time', $end_time],
                ['<', 'yz_last_callback_time', $start_time]
            ])
            ->asArray()
            ->all();
        $row = [];
        $temp = '';
        foreach ($kfFollowData as $key => $value) {
            if ($value['belong_member_id'] == 0) {
                $temp .= $value['id'] . "==>" . $value['belong_member_id'] . "\n";
            }
            if (isset($row[$value['belong_member_id']])) {
                if ($value['kf_last_callback_time'] <= $end_time && $value['kf_last_callback_time'] >= $start_time) {
                    $row[$value['belong_member_id']]['achieve_callback']++;
                }
                if ($value['kf_last_callback_time'] < $start_time && $value['kf_next_callback_time'] >= $start_time && $value['kf_next_callback_time'] <= $end_time) {
                    $row[$value['belong_member_id']]['no_callback']++;
                }
            } else {
                $row[$value['belong_member_id']] = [
                    'date_time' => date("Y-m-d", strtotime('-1 day')),
                    'project_id' => $value['project_id'],
                    'belong_member_id' => $value['belong_member_id'],
                    'achieve_callback' => 0,
                    'no_callback' => 0,
                    'created_at' => time(),
                    'updated_at' => time(),
                ];
                if ($value['kf_last_callback_time'] <= $end_time && $value['kf_last_callback_time'] >= $start_time) {
                    $row[$value['belong_member_id']]['achieve_callback']++;
                }
                if ($value['kf_last_callback_time'] < $start_time && $value['kf_next_callback_time'] >= $start_time && $value['kf_next_callback_time'] <= $end_time) {
                    $row[$value['belong_member_id']]['no_callback']++;
                }
            }
        }
        $row2 = [];
        foreach ($yzFollowData as $key => $value) {
            if ($value['belong_assistant_id'] == 0) {
                $temp .= $value['id'] . "==>" . $value['belong_assistant_id'] . "\n";
            }
            if (isset($row2[$value['belong_assistant_id']])) {
                if ($value['yz_last_callback_time'] <= $end_time && $value['yz_last_callback_time'] >= $start_time) {
                    $row2[$value['belong_assistant_id']]['achieve_callback']++;
                }
                if ($value['yz_last_callback_time'] < $start_time && $value['yz_next_callback_time'] >= $start_time && $value['yz_next_callback_time'] <= $end_time) {
                    $row2[$value['belong_assistant_id']]['no_callback']++;
                }
            } else {
                $row2[$value['belong_assistant_id']] = [
                    'date_time' => date("Y-m-d", strtotime('-1 day')),
                    'project_id' => $value['project_id'],
                    'belong_member_id' => $value['belong_assistant_id'],
                    'achieve_callback' => 0,
                    'no_callback' => 0,
                    'created_at' => time(),
                    'updated_at' => time(),
                ];
                if ($value['yz_last_callback_time'] <= $end_time && $value['yz_last_callback_time'] >= $start_time) {
                    $row2[$value['belong_assistant_id']]['achieve_callback']++;
                }
                if ($value['yz_last_callback_time'] < $start_time && $value['yz_next_callback_time'] >= $start_time && $value['yz_next_callback_time'] <= $end_time) {
                    $row2[$value['belong_assistant_id']]['no_callback']++;
                }
            }
        }
        $ret = array_merge($row, $row2);
        if ($temp) {
            file_put_contents('/data/wwwlogs/report_callback.log', date("Y-m-d") . "==>" . $temp . "\n", FILE_APPEND);
        }
        $col = ['date_time', 'project_id', 'belong_member_id', 'achieve_callback', 'no_callback', 'created_at', 'updated_at'];
        try {
            $num = Yii::$app->db->createCommand()->batchInsert(ReportCallback::tableName(), $col, $ret)->execute();
        } catch (\Exception $e) {
            throw new HttpException(422, '执行失败！');
        }

        return 'success';
    }

    public function callbacknum()
    {
        ini_set('memory_limit', '128M');
        for ($i = 1; $i <= 13; $i++) {
            echo $i . "\n";
            /*if ($i>1){
                break;
            }*/
            $list = Callback::find()
                ->alias('a')
                ->leftJoin(Attr::tableName() . ' as b', 'a.member_id=b.member_id')
                ->select(['a.patient_user_id', 'a.member_id', 'b.profession_id'])
                ->where([
                    'and',
                    ['a.project_id' => $i],
                    ['a.status' => Callback::STATUS_ENABLE]
                ])
                ->asArray()
                ->all();
            $row = [];
            $row_customer = [];
            $row_other = [];
            $row_count = [];
            foreach ($list as $value) {
                if (!isset($row_count[$value['patient_user_id']])) {
                    $row_count[$value['patient_user_id']] = 0;
                }
                $row_count[$value['patient_user_id']]++;

                if ($value['profession_id'] == 301) {
                    if (!isset($row[$value['patient_user_id']])) {
                        $row[$value['patient_user_id']] = 0;
                    }
                    $row[$value['patient_user_id']]++;
                } elseif ($value['profession_id'] == 302) {
                    if (!isset($row_customer[$value['patient_user_id']])) {
                        $row_customer[$value['patient_user_id']] = 0;
                    }
                    $row_customer[$value['patient_user_id']]++;
                } else {
                    if (!isset($row_other[$value['patient_user_id']])) {
                        $row_other[$value['patient_user_id']] = 0;
                    }
                    $row_other[$value['patient_user_id']]++;
                }
            }

            /*if ($i==1){
                print_r(implode(',',$row));
                echo "\n";
                print_r(implode(',',$row_customer));
                echo "\n";
                print_r(implode(',',$row_other));
                echo "\n";
            }
            break;*/
            foreach ($row as $key => $value) {
                User::updateAll(['yz_callback_count' => $value], ['id' => $key]);
            }
            foreach ($row_customer as $key => $value) {
                User::updateAll(['kf_callback_count' => $value], ['id' => $key]);
            }
            foreach ($row_count as $key => $value) {
                User::updateAll(['callback_count' => $value], ['id' => $key]);
            }
            sleep(3);
        }

    }

    /**
     * 过期未回访
     *
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @return mixed
     */
    public function getUnfollowListPage(array $params = [], int $page = 0, int $pageSize = 0)
    {
        $start_time = '';
        $end_time = '';
        switch ($params['unfollow_time']) {
            case 1:
                $start_time = strtotime(date('Y-m-d 00:00:00', strtotime('-1 day')));
                $end_time = strtotime(date('Y-m-d 23:59:59', strtotime('-1 day')));
                break;
            case 2:
                $start_time = strtotime(date('Y-m-d 00:00:00', strtotime('-10 day')));
                $end_time = strtotime(date('Y-m-d 23:59:59', strtotime('-1 day')));
                break;
            case 3:
                $start_time = strtotime(date('Y-m-d 00:00:00', strtotime('-20 day')));
                $end_time = strtotime(date('Y-m-d 23:59:59', strtotime('-10 day')));
                break;
            case 4:
                $start_time = strtotime(date('Y-m-d 00:00:00', strtotime('-40 day')));
                $end_time = strtotime(date('Y-m-d 23:59:59', strtotime('-20 day')));
                break;
            case 5:
                $start_time = strtotime(date('Y-m-d 00:00:00', strtotime('-60 day')));
                $end_time = strtotime(date('Y-m-d 23:59:59', strtotime('-40 day')));
                break;
            case 6:
                $start_time = '';
                $end_time = strtotime(date('Y-m-d 00:00:00', strtotime('-60 day')));
                break;
            default:
                $start_time = '';
                $end_time = strtotime(date('Y-m-d 23:59:59', strtotime('-1 day')));
                break;
        }
        $query = User::find()->select([
            'a.id',
            'a.project_id',
            'a.patient_card_id',
            'a.name',
            'a.age',
            'a.gender',
            'a.mobile',
            'a.city_name',
            'a.belong_member_id',
            'a.belong_assistant_id',
            'a.patient_tags_name',
            'a.last_callback_time',
            'a.kf_last_callback_time',
            'a.yz_last_callback_time',
            'a.last_revisiting_time',
            'a.next_callback_time',
            'a.kf_next_callback_time',
            'a.yz_next_callback_time',
            'a.kf_last_callback_user',
            'a.next_revisiting_time',
            'a.outpatient_type_id',
            'a.source_channel_id',
            'a.callback_count',
            'a.kf_callback_count',
            'a.yz_callback_count',
            'a.yz_last_callback_user',
            'a.missed_days',
            'a.revisiting_count',
            'a.remark',
            'b.source_name',
            'c.outpatient_name',
            'd.name AS clinic_name',
            'a.patient_diseases_id',
            'a.city_id',
            'a.degree_num',
            'group_concat(f.body_parts_id) AS body_parts_id',
        ])
            ->alias('a')
            ->leftJoin(SourceChannel::tableName() . ' AS b', 'b.id = a.source_channel_id')
            ->leftJoin(OutpatientType::tableName() . ' AS c', 'c.id = a.outpatient_type_id')
            ->leftJoin(Clinic::tableName() . ' AS d', 'd.id = a.clinic_id')
            ->leftJoin(Tags::tableName() . ' AS e', 'e.patient_user_id = a.id')
            ->leftJoin(BodyParts::tableName() . ' AS f', 'f.patient_user_id = a.id')
            ->where([
                'a.project_id' => $params['project_id'],
                'a.status' => [User::STATUS_INVALID, User::STATUS_ENABLE],
            ]);
        if ($params['customer'] == 1) {
            $query->andWhere(['>', 'a.belong_member_id', 0]);
        } else {
            $query->andWhere(['>', 'a.belong_assistant_id', 0]);
        }
        if (Yii::$app->user->identity->member->is_super == Member::IS_SUPER_NO) {
            $attr = Yii::$app->services->attr->findInfo([
                'member_id' => Yii::$app->user->identity->member_id,
                'project_id' => $params['project_id'],
            ]);
            if ($attr->is_department_leader == Attr::IS_DEPARTMENT_LEADER_NO) {// 普通员工【自己】
                $memberList = [Yii::$app->user->identity->member_id];
            } elseif ($attr->is_department_leader == Attr::IS_DEPARTMENT_LEADER_YES) {// 部门负责人【部门下所有员工】
                $attrList = Yii::$app->services->attr->findList([
                    'project_id' => $params['project_id'],
                    'department_id' => $attr->department_id,
                ]);
                $memberList = array_column($attrList, 'member_id');
            } else {// 项目负责人【项目下员工】
                $attrList = Yii::$app->services->attr->findList(['project_id' => $params['project_id']]);
                $memberList = array_column($attrList, 'member_id');
            }
            if ($params['customer'] == 1) {
                $query->andWhere(['in', 'a.belong_member_id', $memberList]);
            } else {
                $query->andWhere(['in', 'a.belong_assistant_id', $memberList]);
            }
        }

        if (isset($params['keywords']) && $params['keywords']) {
            // 关键词
            if (isset($params['keywords']) && $params['keywords']) {
                if (preg_match("/([\x81-\xfe][\x40-\xfe])/", $params['keywords'], $match) || preg_match("/(^[A-Za-z]+$)/",$params['keywords'])) {
                    $query->andWhere(['like', 'a.name', "{$params['keywords']}%", false]);
                } else {
                    $query->andWhere([
                        'or',
                        ['a.mobile' => trim($params['keywords'])],
                        ['a.patient_card_id' => trim($params['keywords'])],
                    ]);
                }
            }
        } else {
            // 标签
            if (isset($params['tags_id']) && $params['tags_id']) {
                $query->andWhere(['in', 'e.tags_id', array_filter(explode(',', $params['tags_id']))]);
            }
            // 日期
            if ($start_time) {
                if ($params['customer'] == 1) {
                    $query->andWhere(['>=', 'a.kf_last_callback_time', $start_time]);
                } else {
                    $query->andWhere(['>=', 'a.yz_last_callback_time', $start_time]);
                }
            }
            if ($end_time) {
                if ($params['customer'] == 1) {
                    $query->andWhere(['<=', 'a.kf_last_callback_time', $end_time]);
                } else {
                    $query->andWhere(['<=', 'a.yz_last_callback_time', $end_time]);
                }
            }
            if ($params['customer'] == 1) {
                $query->andWhere(['<', 'a.kf_next_callback_time', time()]);
            } else {
                $query->andWhere(['<', 'a.yz_next_callback_time', time()]);
            }
            /*if ($start_time && $end_time) {
                $query->andWhere(['<=', 'a.last_callback_time', $start_time]);
            } else {
                $query->andWhere(['<=', 'a.last_callback_time', $end_time]);
            }*/

            // 归属人
            if (isset($params['belong_member_id']) && $params['belong_member_id']) {
                if ($params['customer'] == 1) {
                    $query->andWhere(['a.belong_member_id' => $params['belong_member_id']]);
                } else {
                    $query->andWhere(['a.belong_assistant_id' => $params['belong_member_id']]);
                }
            }
            // 就诊类型
            if (isset($params['outpatient_type_id']) && $params['outpatient_type_id']) {
                $query->andWhere(['a.outpatient_type_id' => $params['outpatient_type_id']]);
            }


            // 上次回访人
            if (isset($params['last_callback_user_id']) && $params['last_callback_user_id']) {
                if ($params['customer'] == 1) {
                    $query->andWhere(['a.kf_last_callback_id' => $params['last_callback_user_id']]);
                    $query->andWhere('`kf_last_callback_time` > `yz_last_callback_time`');
                } else if ($params['customer'] == 2) {
                    $query->andWhere(['a.yz_last_callback_id' => $params['last_callback_user_id']]);
                    $query->andWhere('`yz_last_callback_time` > `kf_last_callback_time`');
                }
            }
        }


        // 排序
        $orderBy = [];
        if (isset($params['last_revisiting_time_type']) && $params['last_revisiting_time_type']) {// 上次到诊时间
            if ($params['last_revisiting_time_type'] == 1) {
                $orderBy = ['a.last_revisiting_time' => SORT_ASC];
            } elseif ($params['last_revisiting_time_type'] == 2) {
                $orderBy = ['a.last_revisiting_time' => SORT_DESC];
            }
        } elseif (isset($params['next_revisiting_time_type']) && $params['next_revisiting_time_type']) {// 下次复诊次数
            if ($params['next_revisiting_time_type'] == 1) {
                $orderBy = ['a.next_revisiting_time' => SORT_ASC];
            } elseif ($params['next_revisiting_time_type'] == 2) {
                $orderBy = ['a.next_revisiting_time' => SORT_DESC];
            }
        } elseif (isset($params['last_callback_time_type']) && $params['last_callback_time_type']) {// 上次回访时间
            if ($params['customer'] == 1) {
                if ($params['last_callback_time_type'] == 1) {
                    $orderBy = ['a.kf_last_callback_time' => SORT_ASC];
                } elseif ($params['last_callback_time_type'] == 2) {
                    $orderBy = ['a.kf_last_callback_time' => SORT_DESC];
                }
            } else {
                if ($params['last_callback_time_type'] == 1) {
                    $orderBy = ['a.yz_last_callback_time' => SORT_ASC];
                } elseif ($params['last_callback_time_type'] == 2) {
                    $orderBy = ['a.yz_last_callback_time' => SORT_DESC];
                }
            }
        } elseif (isset($params['next_callback_time_type']) && $params['next_callback_time_type']) {// 下次回访时间
            if ($params['customer'] == 1) {
                if ($params['next_callback_time_type'] == 1) {
                    $orderBy = ['a.kf_next_callback_time' => SORT_ASC];
                } elseif ($params['next_callback_time_type'] == 2) {
                    $orderBy = ['a.kf_next_callback_time' => SORT_DESC];
                }
            } else {
                if ($params['next_callback_time_type'] == 1) {
                    $orderBy = ['a.yz_next_callback_time' => SORT_ASC];
                } elseif ($params['next_callback_time_type'] == 2) {
                    $orderBy = ['a.yz_next_callback_time' => SORT_DESC];
                }
            }
        } elseif (isset($params['sort_revisiting_type']) && $params['sort_revisiting_type']) {// 复诊次数
            if ($params['sort_revisiting_type'] == 1) {
                $orderBy = ['a.revisiting_count' => SORT_ASC];
            } elseif ($params['sort_revisiting_type'] == 2) {
                $orderBy = ['a.revisiting_count' => SORT_DESC];
            }
        } elseif (isset($params['sort_missed_type']) && $params['sort_missed_type']) {// 未到诊天数
            if ($params['sort_missed_type'] == 1) {
                $orderBy = ['a.missed_days' => SORT_ASC];
            } elseif ($params['sort_missed_type'] == 2) {
                $orderBy = ['a.missed_days' => SORT_DESC];
            }
        } elseif (isset($params['sort_unfollow_type']) && $params['sort_unfollow_type']) {// 过期天数
            if ($params['customer'] == 1) {
                if ($params['sort_unfollow_type'] == 1) {
                    $orderBy = ['a.kf_last_callback_time' => SORT_ASC];
                } elseif ($params['sort_unfollow_type'] == 2) {
                    $orderBy = ['a.kf_last_callback_time' => SORT_DESC];
                }
            } else {
                if ($params['sort_unfollow_type'] == 1) {
                    $orderBy = ['a.yz_last_callback_time' => SORT_ASC];
                } elseif ($params['sort_unfollow_type'] == 2) {
                    $orderBy = ['a.yz_last_callback_time' => SORT_DESC];
                }
            }
        } elseif (isset($params['sort_callback_count_type']) && $params['sort_callback_count_type']) {// 回访次数
            if ($params['customer'] == 1) {
                if ($params['sort_callback_count_type'] == 1) {
                    $orderBy = ['a.callback_count' => SORT_ASC];
                } elseif ($params['sort_callback_count_type'] == 2) {
                    $orderBy = ['a.callback_count' => SORT_DESC];
                }
            } else {
                if ($params['sort_callback_count_type'] == 1) {
                    $orderBy = ['a.callback_count' => SORT_ASC];
                } elseif ($params['sort_callback_count_type'] == 2) {
                    $orderBy = ['a.callback_count' => SORT_DESC];
                }
            }
        } else {
            $orderBy = ['a.updated_at' => SORT_DESC];
        }
        $orderBy['a.id'] = SORT_DESC;

        $query->orderBy($orderBy)->groupBy('a.id');
        // 总数
        $total = $query->count();

        // 分页
        if ($page && $pageSize) {
            $query->limit($pageSize)->offset(($page - 1) * $pageSize);
        }

        $list = $query->asArray()->all();

        return [
            'page' => (int)$page,
            'pageSize' => (int)$pageSize,
            'total' => (int)$total,
            'list' => $list,
        ];
    }

    /**
     * 月度 已回访次数、总已回访次数
     * @param int $project_id
     * @return array
     */
    public function visitsNum(array $params = [])
    {
        $project_id = $params['project_id'];

        $follow_time = isset($params['follow_time']) ? $params['follow_time'] : 'month';
        $user = new UserService();
        $followTime = $user->getChooseTime($follow_time, 1);

        $start_time = strtotime(date("Y-m-01 00:00:00"));
        $end_time = strtotime(date("Y-m-d 23:59:59"));

        $callbackList = Callback::find()
            ->select(['created_at'])
            ->where([
                'and',
                ['project_id' => $project_id],
                ['status' => Callback::STATUS_ENABLE],
                ['member_id' => Yii::$app->user->identity->member_id]
            ])
            ->asArray()
            ->all();
        $list = [
            'count_follow' => count($callbackList),
            'month_follow_add' => 0,
            'month_follow_add_stime' => date("Y-m-d", $followTime['start_time']),
            'month_follow_add_etime' => date("Y-m-d", $followTime['end_time']),
        ];
        foreach ($callbackList as $value) {
            if ($value['created_at'] >= $followTime['start_time'] && $value['created_at'] <= $followTime['end_time']) {
                $list['month_follow_add']++;
            }
        }

        return $list;
    }

    /**
     * 回访报表
     * @param array $params
     * @return array
     * @author chenyuebin
     */
    public function callbackReport(array $params = [])
    {
        if (isset($params['date_choose']) && $params['date_choose'] == 1) {
            switch ($params['date_type']) {
                case 'week':
                    $weekTime = $this->getDay();
                    $dateArr = $weekTime['week'];
                    $timeArr = $weekTime['day_time'];
                    $start_time = strtotime($weekTime['day_time'][0]['start_time']);
                    $end_time = strtotime($weekTime['day_time'][count($weekTime['day_time']) - 1]['end_time']);
                    break;
                case 'month':
                    $monthTime = $this->getDayByMonth();
                    $dateArr = $monthTime['day'];
                    $timeArr = $monthTime['day_time'];
                    $start_time = strtotime($monthTime['day_time'][0]['start_time']);
                    $end_time = strtotime($monthTime['day_time'][count($monthTime['day_time']) - 1]['end_time']);
                    break;
                case 'year':
                    $yearTime = $this->getMonthByYear();
                    $dateArr = $yearTime['month'];
                    $timeArr = $yearTime['day_time'];
                    $start_time = strtotime($yearTime['day_time'][0]['start_time']);
                    $end_time = strtotime($yearTime['day_time'][count($yearTime['day_time']) - 1]['end_time']);
                    break;
            }
            $reqParams = [
                'start_time' => $start_time,
                'end_time' => $end_time,
                'project_id' => $params['project_id']
            ];
        } else {
            $start_time = strtotime(date("Y-m-d 00:00:00", strtotime($params['start_time'])));
            $end_time = strtotime(date("Y-m-d 23:59:59", strtotime($params['end_time'])));
            $reqParams = [
                'start_time' => $start_time,
                'end_time' => $end_time,
                'project_id' => $params['project_id']
            ];
            $diffTime = ($end_time - $start_time) / 86400;
            $dateArr = [];// 时间段数组
            $timeArr = [];
            if ($diffTime == 0) {
                $dateArr[] = date("d", strtotime($params['start_time'])) . '日';
                $timeArr[] = [
                    'start_time' => strtotime(date("Y-m-d 00:00:00", $start_time)),
                    'end_time' => strtotime(date("Y-m-d 23:59:59", $end_time))
                ];
            } elseif ($diffTime > 0 && $diffTime <= 15) {
                $dateArr = $this->getDateFromRange($params['start_time'], $params['end_time']);
                foreach ($dateArr as $key => $value) {
                    $timeArr[$key] = [
                        'start_time' => strtotime(date("Y-m-d 00:00:00", strtotime($value))),
                        'end_time' => strtotime(date("Y-m-d 23:59:59", strtotime($value)))
                    ];
                }
                foreach ($dateArr as $key => $value) {
                    $dateArr[$key] = date("d", strtotime($value)) . '日';
                }
            } elseif ($diffTime > 15 && $diffTime <= 90) {
                $dateArrList = $this->getTimeList($params['start_time'], $params['end_time']);
                foreach ($dateArrList as $key => $value) {
                    $dateArr[$key] = $key . '周';
                }
                foreach ($dateArrList as $key => $value) {
                    $timeArr[$key] = [
                        'start_time' => strtotime(date("Y-m-d 00:00:00", strtotime($value['weekStart']))),
                        'end_time' => strtotime(date("Y-m-d 23:59:59", strtotime($value['weekEnd'])))
                    ];
                    $value['weekStart'] = date("Y-m-d", strtotime($value['weekStart']));
                    $value['weekEnd'] = date("Y-m-d", strtotime($value['weekEnd']));
//                    $dateArr[$key] = implode('~', $value);
                }
            } elseif ($diffTime > 90 && $diffTime <= 366) {
                $dateArrList = $this->get_months($params['start_time'], $params['end_time']);
                foreach ($dateArrList as $key => $value) {
                    $dateArr[$key] = implode('~', $value);
                    $timeArr[$key] = [
                        'start_time' => strtotime(date("Y-m-d 00:00:00", strtotime($value['month_start']))),
                        'end_time' => strtotime(date("Y-m-d 23:59:59", strtotime($value['month_end'])))
                    ];
                    $dateArr[$key] = date('m', strtotime($value['month_start'])) . '月';
                }
            }
        }

        // 回访状态处理
        $dataState = $this->getCallbackState($reqParams);
        $stateArr = [];// 定义状态数据数组
        $stateList = [];// 定义状态数组
        foreach ($dataState as $key => $value) {
            $stateList[] = $value['callback_state'];
            $stateArr[$key]['value'] = $value['countState'];
            $stateArr[$key]['name'] = $value['callback_state'];
        }

        // 回访曲线处理
        $data = $this->getCallbackData($reqParams);
        $res = [];
        foreach ($timeArr as $key => $value) {
            $res[$key] = [
                'achieve_callback' => 0,
                'no_callback' => 0
            ];
            foreach ($data as $k => $val) {
                if (strtotime($val['date_time']) >= $value['start_time'] && strtotime($val['date_time']) <= $value['end_time']) {
                    $res[$key]['achieve_callback'] += $val['achieve_callback'];
                    $res[$key]['no_callback'] += $val['no_callback'];
                }
            }
        }
        $ret_achieve = [];// 定义已回访数组
        $ret_no = [];// 定义未回访数组
        foreach ($res as $key => $value) {
            foreach ($value as $k => $val) {
                if ($k == 'achieve_callback') {
                    array_push($ret_achieve, $val);
                }
                if ($k == 'no_callback') {
                    array_push($ret_no, $val);
                }
            }
        }

        // 返回结果
        $ret = [
            'time_list' => $dateArr,
            'achieve_callback' => $ret_achieve,
            'no_callback' => $ret_no,
            'state_arr' => $stateArr,
            'state_list' => $stateList,
        ];
        return $ret;
    }

    /**
     * 回访曲线
     * @param array $params
     * @return mixed
     */
    public function getCallbackData(array $params = [])
    {
        $query = ReportCallback::find()
            ->select(['id', 'date_time', 'achieve_callback', 'no_callback'])
            ->where([
                'project_id' => $params['project_id']
            ])
            ->andWhere([
                'and',
                ['>=', 'created_at', $params['start_time']],
                ['<=', 'created_at', $params['end_time']]
            ]);
        if (Yii::$app->user->identity->member->is_super == Member::IS_SUPER_NO) {
            $query->andWhere(['belong_member_id' => Yii::$app->user->identity->member_id]);
        }
        $query = $query->asArray()
            ->all();
        return $query;
    }

    /**
     * 回访状态
     * @param array $params
     * @return mixed
     */
    public function getCallbackState(array $params = [])
    {
        $query = Callback::find()
            ->select(['count(id) as countState,callback_state,callback_state_id'])
            ->where([
                'project_id' => $params['project_id'],
                'status' => Callback::STATUS_ENABLE,
            ])
            ->andWhere([
                'and',
                ['>=', 'current_callback_time', $params['start_time']],
                ['<=', 'current_callback_time', $params['end_time']]
            ]);
        if (Yii::$app->user->identity->member->is_super == Member::IS_SUPER_NO) {
            $query->andWhere(['member_id' => Yii::$app->user->identity->member_id]);
        }
        $query = $query->groupBy(['callback_state_id'])
            ->asArray()
            ->all();

        return $query;
    }

    /**
     * 获取指定日期段内每一天的日期
     * @param Date $startdate 开始日期
     * @param Date $enddate 结束日期
     * @param $startdate
     * @param $enddate
     * @return array
     */
    function getDateFromRange($startdate, $enddate)
    {

        $stimestamp = strtotime($startdate);
        $etimestamp = strtotime($enddate);

        // 计算日期段内有多少天
        $days = ($etimestamp - $stimestamp) / 86400 + 1;

        // 保存每天日期
        $date = array();

        for ($i = 0; $i < $days; $i++) {
            $date[] = date('Y-m-d', $stimestamp + (86400 * $i));
        }

        return $date;
    }

    /**
     * 获取时间段内每周的起始日期
     * @param $startTime
     * @param $endTime
     * @return array|bool
     */
    function getTimeList($startTime, $endTime)
    {
        //开始时间
        $startDate = $startTime;
        //结束时间
        $endDate = $endTime;
        //跨越天数
        $n = (strtotime($endDate) - strtotime($startDate)) / 86400;
        //结束时间加一天(sql语句里用的是小于和大于，如果有等于的话这句可以不要)
        $endDate = date("Y-m-d 00:00:00", strtotime("$endDate +1 day"));
        //判断，跨度小于7天，可能是同一周，也可能是两周
        if ($n < 7) {
            //查开始时间 在 那周 的 位置
            $day = date("w", strtotime($startDate)) - 1;
            //查开始时间 那周 的 周一
            $week_start = date("Y-m-d 00:00:00", strtotime("$startDate -{$day} day"));
            //查开始时间 那周 的 周末
            $day = 7 - $day;
            $week_end = date("Y-m-d 00:00:00", strtotime("$startDate +{$day} day"));
            //判断周末时间是否大于时间段的结束时间，如果大于，那就是时间段在同一周，否则时间段跨两周
            if ($week_end >= $endDate) {
                $weekList[] = array('weekStart' => $startDate, 'weekEnd' => $endDate);
            } else {
                $weekList[] = array('weekStart' => $startDate, 'weekEnd' => $week_end);
                $weekList[] = array('weekStart' => $week_end, 'weekEnd' => $endDate);
            }
        } else {
            //如果跨度大于等于7天，可能是刚好1周或跨2周或跨N周，先找出开始时间 在 那周 的 位置和那周的周末时间
            $day = date("w", strtotime($startDate)) - 1;
            $week_start = date("Y-m-d 00:00:00", strtotime("$startDate -{$day} day"));
            $day = 7 - $day;
            $week_end = date("Y-m-d 00:00:00", strtotime("$startDate +{$day} day"));
            //先把开始时间那周写入数组
            $weekList[] = array('weekStart' => $startDate, 'weekEnd' => $week_end);
            //判断周末是否大于等于结束时间，不管大于(2周)还是等于(1周)，结束时间都是时间段的结束时间。
            if ($week_end >= $endDate) {
                $weekList[] = array('weekStart' => $week_end, 'weekEnd' => $endDate);
            } else {
                //N周的情况用while循环一下，然后写入数组
                while ($week_end <= $endDate) {
                    $start = $week_end;
                    $week_end = date("Y-m-d 00:00:00", strtotime("$week_end +7 day"));
                    if ($week_end <= $endDate) {
                        $weekList[] = array('weekStart' => $start, 'weekEnd' => $week_end);
                    } else {
                        $weekList[] = array('weekStart' => $start, 'weekEnd' => $endDate);
                    }
                }
            }
        }

        return $weekList;
    }

    /**
     * 获取指定日期之间的各个月
     */
    public function get_months($sdate, $edate)
    {
        $tempDate = $sdate;
        $returnData = [];
        $i = 0;
        while (strtotime($tempDate) < strtotime($edate)) {
            $temp = [];
            $month = strtotime('+' . $i . ' month', strtotime($sdate));
//            $temp['name'] = date('Y-m', $month);
            if ($i == 0) {
                $temp['month_start'] = $sdate;
            } else {
                $temp['month_start'] = date('Y-m-01', $month);
            }
            $temp['month_end'] = date('Y-m-t', $month);
            $tempDate = $temp['month_end'];
            $returnData[] = $temp;
            $i++;
        }
        return $returnData;
    }

    /**
     * 根据指定日期获取所在月的起始时间和结束时间
     */
    public function get_monthinfo_by_date($date)
    {
        $ret = array();
        $timestamp = strtotime($date);
        $mdays = date('t', $timestamp);
        return array(
            'month_start_day' => date('Y-m-1', $timestamp),
            'month_end_day' => date('Y-m-' . $mdays, $timestamp)
        );
    }

    /**
     * 截取日期中的月份和日
     * @param string $date
     * @return string $date
     */
    public function substr_date($date)
    {
        if (!$date) return FALSE;
        return date('Y-m-d', strtotime($date));
    }

    /**
     * 本周的每一天
     * @return mixed
     * @author chenyuebin
     */
    public function getDay()
    {
        $timestr = time();    //当前时间戳
        $now_day = date('w', $timestr);  //当前是周几

        //获取周一
        $monday_str = $timestr - ($now_day - 1) * 60 * 60 * 24;
        $monday = date('Y-m-d', $monday_str);

        //获取周日
        $sunday_str = $timestr + (7 - $now_day) * 60 * 60 * 24;
        $sunday = date('Y-m-d', $sunday_str);

        for ($i = 0; $i < 7; $i++) {
            $arr['day_time'][$i]['start_time'] = date('Y-m-d 00:00:00', strtotime($monday . '+' . $i . 'day'));
            $arr['day_time'][$i]['end_time'] = date('Y-m-d 23:59:59', strtotime($monday . '+' . $i . 'day'));
            switch ($i) {
                case 0;
                    $day = '一';
                    break;
                case 1;
                    $day = '二';
                    break;
                case 2;
                    $day = '三';
                    break;
                case 3;
                    $day = '四';
                    break;
                case 4;
                    $day = '五';
                    break;
                case 5;
                    $day = '六';
                    break;
                case 6;
                    $day = '日';
                    break;
            }
            $arr['week'][] = '周' . $day;
        }
        return $arr;
    }

    /**
     * 本月的每一天
     * @return mixed
     * @author chenyuebin
     */
    public function getDayByMonth()
    {
        $days = date("t");

        for ($i = 0; $i < intval($days); $i++) {
            # 获取当月每天
            $day[] = date('m/d', strtotime("+" . $i . " day", strtotime(date("Y-m-01"))));
            # 获取每天开始时间
            $start = date('Y-m-d H:i:s', strtotime("+" . $i . " day", strtotime(date("Y-m-01 00:00:00"))));
            # 获取每天结束时间
            $end = date('Y-m-d H:i:s', strtotime("+" . $i . " day", strtotime(date("Y-m-01 23:59:59"))));
            $arr['day_time'][$i]['start_time'] = $start;
            $arr['day_time'][$i]['end_time'] = $end;
            $arr['day'][] = ($i + 1) . '日';
        }
        return $arr;
    }

    /**
     * 本年的每月起始日期
     * @return mixed
     * @author chenyuebin
     */
    public function getMonthByYear()
    {
        $currentTime = strtotime(date("Y-01-01 00:00:00"));
        $cyear = floor(date("Y", $currentTime));
        $cMonth = floor(date("m", $currentTime));
        for ($i = 0; $i < 12; $i++) {
            $nMonth = $cMonth + $i;
            $cyear = $nMonth == 0 ? ($cyear - 1) : $cyear;
            $nMonth = $nMonth <= 0 ? 12 + $nMonth : $nMonth;
            $date = $cyear . "-" . $nMonth . "-1";
            $firstday = date('Y-m-01 00:00:00', strtotime($date));
            $lastday = date('Y-m-t 23:59:59', strtotime($date));

            $arr['day_time'][$i]['start_time'] = $firstday;
            $arr['day_time'][$i]['end_time'] = $lastday;
            switch ($i) {
                case 0;
                    $day = '一';
                    break;
                case 1;
                    $day = '二';
                    break;
                case 2;
                    $day = '三';
                    break;
                case 3;
                    $day = '四';
                    break;
                case 4;
                    $day = '五';
                    break;
                case 5;
                    $day = '六';
                    break;
                case 6;
                    $day = '七';
                    break;
                case 7;
                    $day = '八';
                    break;
                case 8;
                    $day = '九';
                    break;
                case 9;
                    $day = '十';
                    break;
                case 10;
                    $day = '十一';
                    break;
                case 11;
                    $day = '十二';
                    break;
            }
            $arr['month'][] = $day . '月';
        }
        return $arr;
    }

    /**
     * 报表统计回访列表
     *
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @param int $directTotal
     * @return array
     */
    public function getReportMemberListPage(array $params = [], int $page = 0, int $pageSize = 0, int $directTotal = 0)
    {
        $query = Callback::find()->alias('a')
            ->select([
                'a.patient_user_id', 'COUNT(*) AS callback_num', 'GROUP_CONCAT(a.content ORDER BY a.created_at DESC) AS content',
                'GROUP_CONCAT(a.callback_way_id ORDER BY a.created_at DESC) AS callback_way_id',
                'GROUP_CONCAT(a.current_callback_time ORDER BY a.created_at DESC) AS current_callback_time',
                'b.name', 'b.age', 'b.gender', 'b.patient_card_id', 'b.reg_time', 'b.last_revisiting_time', 'b.next_revisiting_time', 'b.missed_days',
                'c.diseases_name'
            ])
            ->innerJoin(User::tableName() . ' AS b', 'b.id = a.patient_user_id')
            ->leftJoin(PatientDiseases::tableName() . ' AS c', 'c.id = b.patient_diseases_id')
            ->innerJoin(Attr::tableName() . ' AS d', 'd.member_id = a.member_id AND d.project_id=a.project_id')
            ->where([
                //'a.project_id' => $params['project_id'],
                //'a.member_id' => $params['member_id'],
                'a.status' => Callback::STATUS_ENABLE,
            ])
            ->groupBy('a.patient_user_id');

        if (isset($params['member_id']) && $params['member_id']) {
            $query->andWhere(['a.member_id' => $params['member_id']]);
        }

        if (isset($params['project_id']) && $params['project_id']) {
            $query->andWhere(['a.project_id' => $params['project_id']]);
        }

        // 类型
        if (isset($params['profession_id'])) {
            if ($params['profession_id'] == 1) {
                $query->andWhere(['d.profession_id' => Profession::ID_CUSTOMER]);
            } elseif ($params['profession_id'] == 2) {
                $query->andWhere(['d.profession_id' => Profession::ID_MEDICAL]);
            }
        }

        // 回访方式
        if (isset($params['callback_way_id']) && $params['callback_way_id']) {
            $query->andWhere(['a.callback_way_id' => $params['callback_way_id']]);
        }

        // 回访状态
        if (isset($params['callback_state_id']) && $params['callback_state_id']) {
            $query->andWhere(['a.callback_state_id' => $params['callback_state_id']]);
        }

        // 回访患者年份
        if (isset($params['reg_time']) && $params['reg_time']) {
            $query->andWhere(['=', new Expression("FROM_UNIXTIME(b.reg_time, '%Y')"), $params['reg_time']]);
        }

        // 开始时间
        if (isset($params['start_time']) && $params['start_time']) {
            $query->andWhere(['>=', 'a.current_callback_time', strtotime($params['start_time'])]);
        }

        // 结束时间
        if (isset($params['end_time']) && $params['end_time']) {
            $query->andWhere(['<=', 'a.current_callback_time', strtotime($params['end_time'] . ' 23:59:59')]);
        }

        $order = ['a.patient_user_id' => SORT_ASC];

        $data = $this->getListPageRes($query, $page, $pageSize, $order, $directTotal);
        if ($directTotal == 1) {
            return $data;
        }

        return $data;
    }

    /**
     * 统计归属人回访患者次数
     *
     * @param array $params
     * @return array|\yii\db\ActiveRecord[]
     */
    public function statisticsCallbackNum(array $params = [])
    {
        $query = Callback::find()->alias('a')
            ->innerJoin(Attr::tableName() . ' AS b', 'b.member_id = a.member_id AND b.project_id=a.project_id')
            ->select([
                'a.patient_user_id', 'COUNT(*) AS callback_num'
            ])
            ->where([
                //'project_id' => $params['project_id'],
                //'member_id' => $params['member_id'],
                'a.status' => Callback::STATUS_ENABLE,
            ])
            ->groupBy('a.patient_user_id')
            ->indexBy('patient_user_id');

        if (isset($params['project_id']) && $params['project_id']) {
            $query->andWhere(['a.project_id' => $params['project_id']]);
        }

        if (isset($params['member_id']) && $params['member_id']) {
            $query->andWhere(['a.member_id' => $params['member_id']]);
        }

        // 类型
        if (isset($params['profession_id']) && $params['profession_id']) {
            if ($params['profession_id'] == 1) {
                $query->andWhere(['b.profession_id' => Profession::ID_CUSTOMER]);
            } elseif ($params['profession_id'] == 2) {
                $query->andWhere(['b.profession_id' => Profession::ID_MEDICAL]);
            }
        }

        // 开始时间
        if (isset($params['start_time']) && $params['start_time']) {
            $query->andWhere(['>=', 'a.current_callback_time', strtotime($params['start_time'])]);
        }

        // 结束时间
        if (isset($params['end_time']) && $params['end_time']) {
            $query->andWhere(['<=', 'a.current_callback_time', strtotime($params['end_time'] . ' 23:59:59')]);
        }

        return $query->asArray()->all();
    }

    /**
     * 统计归属人回访患者总人数
     *
     * @param array $params
     * @return int|string
     */
    public function statisticsCallbackTotalNum(array $params = [])
    {
        $query = Callback::find()
            ->select([
                'member_id', 'COUNT(DISTINCT patient_user_id) as total_num',
            ])
            ->where([
                'project_id' => $params['project_id'],
                'member_id' => $params['member_id'],
                'status' => Callback::STATUS_ENABLE,
            ])
            ->groupBy('member_id')
            ->indexBy('member_id');

        // 开始时间
        if (isset($params['start_time']) && $params['start_time']) {
            $query->andWhere(['>=', 'current_callback_time', strtotime($params['start_time'])]);
        }

        // 结束时间
        if (isset($params['end_time']) && $params['end_time']) {
            $query->andWhere(['<=', 'current_callback_time', strtotime($params['end_time'] . ' 23:59:59')]);
        }

        return $query->asArray()->all();
    }

    /**
     * 格式化【getReportMemberListPage】
     *
     * @param array $data
     * @param array $params
     * @return array
     */
    public function getReportMemberListPageFormat(array $data = [], array $params = [])
    {
        // 总回访次数
        $totalCallbackNumList = $this->statisticsCallbackNum([
            'project_id' => $params['project_id'],
            'member_id' => $params['member_id'] ?? 0,
            'profession_id' => $params['profession_id'] ?? 0,
        ]);
        // 本月回访次数
        /*$monthCallbackNumList = $this->statisticsCallbackNum([
            'project_id' => $params['project_id'],
            'member_id' => $params['member_id'],
            'start_time' => date('Y-m-01', Yii::$app->params['time'])
        ]);*/

        $list = [];
        foreach ($data as $row) {
            $content = explode(',', $row['content']);
            // 回访时间精确到分钟。回访方式为已选日期的最后一次回访的回访方式
            $callbackWayId = explode(',', $row['callback_way_id']);
            $currentCallbackTime = explode(',', $row['current_callback_time']);

            $list[] = [
                'patient_user_id' => $row['patient_user_id'],
                'name' => $row['name'],
                'age' => $row['age'],
                'gender' => $row['gender'],
                'gender_str' => User::$genders[$row['gender']],
                'patient_card_id' => $row['patient_card_id'],
                'diseases_name' => $row['diseases_name'] ?: '',
                'reg_time_str' => $row['reg_time'] ? date('Y-m-d', $row['reg_time']) : '',
                'last_revisiting_time_str' => $row['last_revisiting_time'] ? date('Y-m-d', $row['last_revisiting_time']) : '',
                'next_revisiting_time_str' => $row['next_revisiting_time'] ? date('Y-m-d', $row['next_revisiting_time']) : '',
                'missed_days' => $row['missed_days'],
                'callback_num' => $row['callback_num'],
                'total_callback_num' => $totalCallbackNumList[$row['patient_user_id']]['callback_num'] ?? 0,
                'content' => $content[0],
                'callback_way' => $callbackWayId ? Callback::$callbackWayIds[$callbackWayId[0]] : '',
                'current_callback_time' => $currentCallbackTime ? date('Y-m-d H:i', $currentCallbackTime[0]) : '',
//                'month_callback_num' => $monthCallbackNumList[$row['patient_user_id']]['callback_num'] ?? 0,
            ];
        }

        return $list;
    }

    /**
     * 我的报表
     *
     * @param array $params
     * @param int $page
     * @param int $pageSzie
     * @return array
     */
    public function myReport(array $params = [], int $page, int $pageSzie)
    {
        // 获取筛选条件
        $condition = [
            'tags_list' => CommonService::getTagsList(),
            'outpatient_type_list' => CommonService::getOutpatientTypeList($params['is_customer']),
        ];

        // 新增患者时间段
        $addDateArr = $this->getTypeDate($params['add_type']);
        // 已到时间段
        $arriveDateArr = $this->getTypeDate($params['arrive_type']);
        // 预到时间段
        $orderArriveDateArr = $this->getTypeDate($params['order_arrive_type'], 0);
        // 过期未到时间段
        $unarriveDateArr = $this->getTypeDate($params['unarrive_type'], 1, 1);
        // 已回访次数时间段
        $callbackDateArr = $this->getTypeDate($params['callback_type']);
        // 过期未回访时间段
        $uncallbackDateArr = $this->getTypeDate($params['uncallback_type'], 1, 1);

        // 1.新增患者【新增人数：分配记录时间属于该时间段&&归属人为当前操作人  总患者数：归属人为医助or客服人数 && 患者状态=0or1】
        $params['start_time'] = $addDateArr['start_time'];
        $params['end_time'] = $addDateArr['end_time'];
        $addData = Yii::$app->services->patientUser->getAddListPage($params, 0, 0, 1);

        // 患者总数
        $addAllNum = Yii::$app->services->patientUser->getAddNum($params);

        // 2.已到【新增人数：上次到诊日期属于该时间段&&当前时间>=上次到诊日期&&归属人为当前操作人  总人数：归属人为当前操作人&&当前时间>=上次到诊日期】last_revisiting_time
        $params['start_time'] = $arriveDateArr['start_time'];
        $params['end_time'] = $arriveDateArr['end_time'];
        $params['outpatient_type_id'] = array_column($condition['outpatient_type_list'], 'id');

        $arriveData = Yii::$app->services->patientUser->getArriveListPage($params, 0, 0, 0, 1);

        // 已到总数
        $arriveAllNum = Yii::$app->services->patientUser->getArriveNum($params);

        // 3.预到【新增人数：下次复诊日期属于该时间段&&归属人为当前操作人&&当前时间<=下次复诊日期  总人数：归属人为当前操作人&&当前时间<=下次复诊日期】next_revisiting_time
        $params['start_time'] = $orderArriveDateArr['start_time'];
        $params['end_time'] = $orderArriveDateArr['end_time'];
        $params['outpatient_type_id'] = array_column($condition['outpatient_type_list'], 'id');
        $orderArriveData = Yii::$app->services->patientUser->getOrderArriveListPage($params, $page, $pageSzie, 0);

        // 预到总数
        $orderArriveAllNum = Yii::$app->services->patientUser->getOrderArriveNum($params);

        // 4.过期未到【新增人数：下次复诊日期属于该时间段&&归属人为当前操作人&&当前时间>下次复诊日期  总人数：归属人为当前操作人&&当前时间>下次复诊日期】next_revisiting_time
        $params['start_time'] = $unarriveDateArr['start_time'];
        $params['end_time'] = $unarriveDateArr['end_time'];
        $params['outpatient_type_id'] = array_column($condition['outpatient_type_list'], 'id');

        $unarriveData = Yii::$app->services->patientUser->getUnarriveListPage($params, 0, 0, 0, 1);

        // 过期未到总数
        $unarriveAllNum = Yii::$app->services->patientUser->getUnarriveNum($params);

        // 5.已回访次数【新增人数：本次回访时间属于该时间段&&回访人为当前操作人  总人数：回访人为当前操作人】current_callback_time
        $params['start_time'] = $callbackDateArr['start_time'];
        $params['end_time'] = $callbackDateArr['end_time'];
        $callbackData = $this->getCallbackListPage($params, 0, 0, 1);

        // 已回访总数
        unset($params['start_time'], $params['end_time']);
        $callbackAllNum = $this->getCallbackListPage($params, 0, 0, 1);

        // 6.过期未回访【新增人数：下次回访时间属于该时间段&&当前时间>下次回访时间  总人数：当前时间>下次回访时间】next_callback_time
        $params['start_time'] = $uncallbackDateArr['start_time'];
        $params['end_time'] = $uncallbackDateArr['end_time'];
        $uncallbackData = Yii::$app->services->patientUser->getUncallbackListPage($params, 0, 0, 1);

        // 过期未回访总数
        unset($params['start_time'], $params['end_time']);
        $uncallbackAllNum = Yii::$app->services->patientUser->getUncallbackListPage($params, 0, 0, 1);

        return [
            'add_num' => $addData['total'],
            'add_all_num' => $addAllNum,
            'arrive_num' => $arriveData['total'],
            'arrive_all_num' => $arriveAllNum,
            'order_arrive_num' => $orderArriveData['total'],
            'order_arrive_all_num' => $orderArriveAllNum,
            'unarrive_num' => $unarriveData['total'],
            'unarrive_all_num' => $unarriveAllNum,
            'callback_num' => $callbackData['total'],
            'callback_all_num' => $callbackAllNum['total'],
            'uncallback_num' => $uncallbackData['total'],
            'uncallback_all_num' => $uncallbackAllNum['total'],
            'page' => $orderArriveData['page'],
            'pageSize' => $orderArriveData['pageSize'],
            'list' => $orderArriveData['list'],
            'condition' => [
                'add_type' => $addDateArr,
                'arrive_type' => $arriveDateArr,
                'order_arrive_type' => $orderArriveDateArr,
                'unarrive_type' => $unarriveDateArr,
                'callback_type' => $callbackDateArr,
                'uncallback_type' => $uncallbackDateArr,
                'outpatient_type_list' => $condition['outpatient_type_list'],
                'tags_list' => $condition['tags_list'],
            ],
        ];
    }

    /**
     * 解析类型时间段
     *
     * @param int $types 类型【1今日、2昨日、3周、4月】
     * @param int $isBefore 是否为之前日期【1是、0否(之后)】
     * @param int $status 计算起始时间【0当天、1前一天】
     * @return array
     */
    public function getTypeDate(int $types, int $isBefore = 1, int $status = 0)
    {
        // 当天凌晨
        $nowDate = date('Y-m-d');
        $nowTimestamp = strtotime($nowDate);

        $data = [
            'start_time' => '',
            'end_time' => '',
        ];
        switch ($types) {
            case 1:// 今日
                $data['start_time'] = $nowDate;
                $data['end_time'] = $nowDate;
                break;
            case 2:// 昨日or明日
                $timestamp = $isBefore == 1 ? $nowTimestamp - 86400 : $nowTimestamp + 86400;
                $date = date('Y-m-d', $timestamp);
                $data['start_time'] = $date;
                $data['end_time'] = $date;
                break;
            case 3:// 周(7天)
                $timestamp = $isBefore == 1 ? $nowTimestamp - 6 * 86400 : $nowTimestamp + 6 * 86400;
                $date = date('Y-m-d', $timestamp);
                if ($isBefore == 1) {
                    $data['start_time'] = $date;
                    $data['end_time'] = $status == 1 ? date('Y-m-d', $nowTimestamp - 86400) : $nowDate;
                } else {
                    $data['start_time'] = $nowDate;
                    $data['end_time'] = $date;
                }
                break;
            case 4:// 月(30天)
                $timestamp = $isBefore == 1 ? $nowTimestamp - 29 * 86400 : $nowTimestamp + 29 * 86400;
                $date = date('Y-m-d', $timestamp);
                if ($isBefore == 1) {
                    $data['start_time'] = $date;
                    $data['end_time'] = $status == 1 ? date('Y-m-d', $nowTimestamp - 86400) : $nowDate;
                } else {
                    $data['start_time'] = $nowDate;
                    $data['end_time'] = $date;
                }
                break;
            default:
                break;
        }

        return $data;
    }

    /**
     * 已回访列表
     *
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @param int $isReturnTotal 是否直接返回总数【1是、0否】
     * @return array
     */
    public function getCallbackListPage(array $params = [], int $page = 0, int $pageSize = 0, int $isReturnTotal = 0)
    {
        $query = Callback::find()->alias('a')
            ->select([
                'a.*'
            ])
            ->where([
                'a.project_id' => $params['project_id'],
                'a.status' => [Callback::STATUS_ENABLE],
            ]);

        // 回访人
        if (isset($params['member_id'])) {
            $query->andWhere(['a.member_id' => $params['member_id']]);
        }

        // 本次回访开始时间
        if (isset($params['start_time']) && $params['start_time']) {
            $query->andWhere(['>=', 'a.current_callback_time', strtotime($params['start_time'])]);
        }

        // 本次回访结束时间
        if (isset($params['end_time']) && $params['end_time']) {
            $query->andWhere(['<=', 'a.current_callback_time', strtotime($params['end_time'] . ' 23:59:59')]);
        }

        // 总数
        $total = $query->count();
        if ($isReturnTotal == 1) {
            return [
                'total' => (int)$total,
            ];
        }

        // 分页
        if ($page && $pageSize) {
            $query->limit($pageSize)->offset(($page - 1) * $pageSize);
        }

        $list = $query->asArray()->all();

        return [
            'page' => (int)$page,
            'pageSize' => (int)$pageSize,
            'total' => (int)$total,
            'list' => $list,
        ];
    }

    /**
     * 获取上一次回访内容
     * @param int $patient_id
     * @return false|string|null
     * @author chenyuebin
     */
    public function lastCallbak(int $patient_id)
    {
        return Callback::find()
            ->select('content')
            ->where([
                'patient_user_id' => $patient_id,
                'status' => Callback::STATUS_ENABLE
            ])
            ->orderBy('id desc')
            ->scalar();
    }
}
